﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace LogitechLCDWrapper
{
    public class MonoLCDScreen : LCDScreen
    {

        #region DLLImports
        [DllImport(DllPath, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
        static extern bool LogiLcdMonoSetText(int lineNumber, StringBuilder text);
        [DllImport(DllPath, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
        static extern bool LogiLcdMonoSetBackground(Byte[] monoBitmap);
        #endregion

        #region Abstract implementation
        private List<LCDButtons> _buttons;
        protected override List<LCDButtons> Buttons
        {
            get
            {
                if (_buttons == null)
                {
                    _buttons = new List<LCDButtons>(new List<LCDButtons>(new[] { LCDButtons.MonoButton1, LCDButtons.MonoButton2, LCDButtons.MonoButton3, LCDButtons.MonoButton4 }));
                }
                return _buttons;
            }
        }
        protected override void Initialize()
        {
            ScreenHeight = 43;
            ScreenWidth = 160;
            MaxLines = 4;
            MaxCharPerLine = 26;
            RefreshFrequency = 60;
            BackgroundSize = ScreenSize;
        }
        protected override void DrawBackground(TimeSpan elapsedTime)
        {
            BeginDrawing();
            byte[] bArray = new byte[ScreenSize];
            for (int y = 0; y < GraphicDevice.ClipBounds.Height && y < ScreenHeight; y++)
            {
                for (int x = 0; x < GraphicDevice.ClipBounds.Width && x < ScreenWidth; x++)
                {

                    var color = Background.GetPixel(x, y);
                    //C'est la couleur noir qui dessine un trait, son code est 0
                    //donc pour que le trait soit visible, il faut que val > 128
                    // je défini arbitrairement qu'une couleur visible sera lorsque la somme de R+G+B > 3 * la moitié de sa valeur max
                    double val = color.A * ((color.R + color.G + color.B) > 3 * 128 ? 0 : 1);
                    bArray[x + y * ScreenWidth] = Convert.ToByte(val);
                }
            }
            LogiLcdMonoSetBackground(bArray);
            EndDrawing();
        }
        protected override void DrawText(TimeSpan elapsedTime)
        {
            for (int i = 0; i < MaxLines; i++)
            {
                string temp = Lines[i];
                if (EnableTextScrolling && Lines[i].Length > MaxCharPerLine)
                {
                    temp = Lines[i].Substring(scrollIndices[i], MaxCharPerLine + scrollIndices[i] > Lines[i].Length ? Lines[i].Length - scrollIndices[i] : MaxCharPerLine);
                    if (DateTime.Now.Ticks > previousScrollTime[i].Ticks + (TimeSpan.TicksPerSecond * ScrollSpeed))
                    {
                        scrollIndices[i] = scrollIndices[i] + MaxCharPerLine >= Lines[i].Length ? scrollIndices[i] - 1 : scrollIndices[i] + 1 * scrollDirection[i];
                        previousScrollTime[i] = DateTime.Now;
                        scrollDirection[i] = scrollIndices[i] >= Lines[i].Length - MaxCharPerLine ? -1 : scrollIndices[i] == 0 ? 1 : scrollDirection[i];
                    }
                }
                LogiLcdMonoSetText(i, new StringBuilder(temp));
            }
        }
        public override bool IsConnected
        {
            get
            {
                return LogiLcdIsConnected((int)LCDType.Mono);
            }
        }
        #endregion

        public MonoLCDScreen(string appName)
            : base(appName, LCDType.Mono)
        {

        }

        /// <summary>
        /// Set image as background
        /// </summary>
        /// <param name="bmp"></param>
        public void DrawImage(System.Drawing.Bitmap bmp)
        {
            BeginDrawing();
            GraphicDevice.DrawImage(bmp, 0, 0);
            EndDrawing();
        }
        /// <summary>
        /// Set pixel on or off
        /// </summary>
        /// <param name="x">X position of the pixel to set</param>
        /// <param name="y">Y position of the pixel to set</param>
        /// <param name="activated">Define if pixel is on or off</param>
        public void SetPixel(double x, double y, bool activated)
        {
            BeginDrawing();
            if (x >= 0 && x < ScreenWidth && y >= 0 && y < ScreenHeight)
            {
                Background.SetPixel((int)x, (int)y, activated ? System.Drawing.Color.Black : System.Drawing.Color.White);
            }
            EndDrawing();
        }
        /// <summary>
        /// Display text on the line
        /// </summary>
        /// <param name="text">Text to display</param>
        /// <param name="line">Number of the line to display text, if line > maxline, line will loop</param>
        public void DisplayText(string text, int line)
        {
            Lines[Math.Abs(line) % MaxLines] = text;
            scrollIndices[Math.Abs(line) % MaxLines] = 1;
        }


    }
}
